package cn.lg.soar.system.biz.modules.auth.service;

import cn.lg.soar.common.util.AssertUtil;
import cn.lg.soar.common.util.current.CurrentProxy;
import cn.lg.soar.core.util.CacheManagerUtils;
import cn.lg.soar.system.biz.modules.auth.entity.Org;
import cn.lg.soar.system.biz.modules.auth.entity.Post;
import cn.lg.soar.system.biz.modules.auth.entity.User;
import cn.lg.soar.system.biz.modules.auth.entity.UserPostRel;
import cn.lg.soar.system.biz.modules.auth.mapper.OrgMapper;
import cn.lg.soar.system.biz.modules.auth.mapper.PostMapper;
import cn.lg.soar.system.biz.modules.auth.mapper.UserMapper;
import cn.lg.soar.system.biz.modules.auth.mapper.UserPostRelMapper;
import cn.lg.soar.system.api.model.UserPostItemVO;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static cn.lg.soar.system.biz.config.SystemCacheKey.*;

/**
 * @author luguoxiang
 * @date 2022/4/10
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public class UserPostRelService extends ServiceImpl<UserPostRelMapper, UserPostRel> implements CurrentProxy<UserPostRelService> {

    @Autowired
    private UserMapper userMapper;
    @Autowired
    private PostMapper postMapper;
    @Autowired
    private OrgMapper orgMapper;

    /**
     * 根据用户id获取机构
     * @param userId
     * @return
     */
    @Cacheable(value = USERID_TO_POSTS, key = "#p0")
    public List<UserPostItemVO> getPosts(Long userId) {
        List<UserPostRel> list = list(
                Wrappers.<UserPostRel>lambdaQuery()
                        .select(
                                UserPostRel::getPostId,
                                UserPostRel::getOrgId,
                                UserPostRel::getMain,
                                UserPostRel::getPostName,
                                UserPostRel::getOrgName
                        )
                        .eq(UserPostRel::getUserId, userId)
        );
        return list.stream().map(x -> {
            UserPostItemVO vo = new UserPostItemVO();
            vo.setPostId(x.getPostId());
            vo.setOrgId(x.getOrgId());
            vo.setMain(x.getMain());
            vo.setPostName(x.getPostName());
            vo.setOrgName(x.getOrgName());
            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * 设置用户机构
     * @param userId
     */
    @CacheEvict(value = { USERID_TO_POSTS, USERID_TO_ALL_ROLEIDS, USERID_TO_ALL_ORGIDS }, key = "#p0")
    @Transactional(rollbackFor = RuntimeException.class)
    public void setUserPost(Long userId, Collection<UserPostItemVO> posts) {
        // 清空旧值
        clearByUser(userId);
        // 批量保存新值
        if (CollectionUtils.isEmpty(posts)) {
            return;
        }
        User user = userMapper.selectById(userId);
        String nickname = user.getNickname();
        Set<Long> postIds = new HashSet<>(posts.size());
        Set<Long> orgIds = new HashSet<>(posts.size());
        Long mainId = null;
        for (UserPostItemVO post : posts) {
            postIds.add(post.getPostId());
            orgIds.add(post.getOrgId());
            if (Boolean.TRUE.equals(post.getMain())) {
                AssertUtil.isTrue(mainId == null, "主职部门只能有一个");
                mainId = post.getOrgId();
            }
        }

        Map<Long, String> postNameMap = postMapper.selectList(
                        Wrappers.<Post>lambdaQuery()
                                .select(Post::getId, Post::getName)
                                .in(Post::getId, postIds)
                ).stream()
                .collect(Collectors.toMap(Post::getId, Post::getName));

        Map<Long, String> orgNameMap = orgMapper.selectList(
                        Wrappers.<Org>lambdaQuery()
                                .select(Org::getId, Org::getName)
                                .in(Org::getId, orgIds)
                ).stream()
                .collect(Collectors.toMap(Org::getId, Org::getName));

        List<UserPostRel> collect = posts.stream()
                .distinct()
                .map(x -> {
                    UserPostRel data = new UserPostRel();
                    data.setUserId(userId);
                    data.setMain(x.getMain());
                    data.setOrgId(x.getOrgId());
                    data.setPostId(x.getPostId());
                    data.setUserName(nickname);
                    data.setPostName(postNameMap.get(x.getPostId()));
                    data.setOrgName(orgNameMap.get(x.getOrgId()));
                    return data;
                })
                .collect(Collectors.toList());
        AssertUtil.isTrue(saveBatch(collect), "保存用户机构失败");
    }

    @CacheEvict(value = { USERID_TO_POSTS, USERID_TO_ALL_ROLEIDS, USERID_TO_ALL_ORGIDS }, key = "#p0")
    public void clearByUser(Long userId) {
        this.remove(Wrappers.<UserPostRel>lambdaQuery().eq(UserPostRel::getUserId, userId));
    }

    /**
     * 获取所有组织id
     * @param userId
     * @return
     */
    public List<Long> getOrgIds(Long userId) {
        List<UserPostItemVO> orgs = proxy().getPosts(userId);
        return orgs.stream().map(UserPostItemVO::getOrgId).distinct().collect(Collectors.toList());
    }

    /**
     * 获取所有岗位id
     * @param userId
     * @return
     */
    public List<Long> getPostIds(Long userId) {
        List<UserPostItemVO> orgs = proxy().getPosts(userId);
        return orgs.stream().map(UserPostItemVO::getPostId).filter(Objects::nonNull).distinct().collect(Collectors.toList());
    }

    /**
     * 获取主职部门
     * @param userId
     * @return
     */
    public UserPostItemVO getMain(Long userId) {
        List<UserPostItemVO> orgs = proxy().getPosts(userId);
        for (UserPostItemVO org : orgs) {
            if (Boolean.TRUE.equals(org.getMain())) {
                return org;
            }
        }
        return null;
    }

    /**
     * 更新岗位
     * @param postId 岗位id
     */
    @CacheEvict(value = { USERID_TO_POSTS, USERID_TO_ALL_ROLEIDS, USERID_TO_ALL_ORGIDS }, allEntries = true)
    public void updatePost(Long postId) {
        Post post = postMapper.selectById(postId);
        AssertUtil.notNull(post, "职位不存在");
        Org org = orgMapper.selectById(post.getOrgId());
        AssertUtil.notNull(org, "组织不存在");
        boolean update = update(
                Wrappers.<UserPostRel>lambdaUpdate()
                        .set(UserPostRel::getPostName, post.getName())
                        .set(UserPostRel::getOrgId, post.getOrgId())
                        .set(UserPostRel::getOrgName, org.getName())
                        .eq(UserPostRel::getPostId, postId)
        );
        if (update) {
            CacheManagerUtils.clear(USERID_TO_POSTS, USERID_TO_ALL_ORGIDS);
        }
    }

    /**
     * 更新用户名称
     * @param userId
     * @param userName
     */
    @CacheEvict(value = USERID_TO_POSTS, key = "#p0")
    public void updateUser(Long userId, String userName) {
        boolean update = update(
                Wrappers.<UserPostRel>lambdaUpdate()
                        .set(UserPostRel::getUserName, userName)
                        .eq(UserPostRel::getUserId, userId)
        );
        if (update) {
            CacheManagerUtils.clear(USERID_TO_POSTS, USERID_TO_ALL_ORGIDS);
        }
    }

    /**
     * 更新组织名称
     * @param orgId
     * @param orgName
     */
    @CacheEvict(value = USERID_TO_POSTS, allEntries = true)
    public void updateOrg(Long orgId, String orgName) {
        boolean update = update(
                Wrappers.<UserPostRel>lambdaUpdate()
                        .set(UserPostRel::getOrgName, orgName)
                        .eq(UserPostRel::getOrgId, orgId)
        );
        if (update) {
            CacheManagerUtils.clear(USERID_TO_POSTS, USERID_TO_ALL_ORGIDS);
        }
    }

}
